package org.xxpay.manage.sys.service;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.common.util.GoogleAuthenticatorUtil;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.XXPayUtil;
import org.xxpay.core.entity.SysLoginFailIpRecord;
import org.xxpay.core.entity.SysUser;
import org.xxpay.manage.common.service.CommonService;
import org.xxpay.manage.secruity.JwtTokenUtil;
import org.xxpay.manage.secruity.JwtUser;

/**
 * Created by dingzhiwei on 17/11/28.
 */
@Component
public class SysUserService {

    @Autowired
    private CommonService commonService;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    private static final MyLog _log = MyLog.getLog(SysUserService.class);

    /**
     * 查询
     * @param userId
     * @return
     */
    public SysUser findByUserId(Long userId) {
        return commonService.sysService.findByUserId(userId);
    }

    public SysUser findByUserName(String userName) {
        return commonService.sysService.findByUserName(userName);
    }

    public String login(String username, String password, String ip, Long googleCode, JSONObject sysConfig) throws ServiceException {
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
        String btSignConfig = sysConfig.getString("btSignConfig");
        String btUrlConfig = sysConfig.getString("btUrlConfig");
        Integer loginCountConfig = sysConfig.getInteger("loginCountConfig");
        Byte loginToBlackType = sysConfig.getByte("loginToBlackType");
        // Perform the security
        try{
            Authentication authentication = authenticationManager.authenticate(upToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }catch (Exception e) {
            if (loginCountConfig != null && loginCountConfig != 0) {
                int count = commonService.sysLoginFileIpRecordService.failCountByIp(ip, btSignConfig, btUrlConfig, loginCountConfig, loginToBlackType, username);
                if (count < 0) {
                    throw new ServiceException(RetEnum.RET_MGR_USER_STOP);
                }
                _log.error(e, "登录失败, 剩余登录次数:"+count);
                throw new ServiceException(RetEnum.RET_MGR_LOGIN_FAIL, "剩余登录次数:"+count);
            }else {
                _log.error(e, "登录失败");
                throw new ServiceException(RetEnum.RET_MGR_LOGIN_FAIL);
            }
        }

        // Reload password post-security so we can generate token
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        // 查看商户状态
        JwtUser jwtUser = (JwtUser) userDetails;
        Byte status = jwtUser.getStatus();
        if(status == MchConstant.MGR_STATUS_STOP) {
            throw new ServiceException(RetEnum.RET_MGR_USER_STOP);
        }

        Long userId = jwtUser.getId();
        SysUser sysUser = commonService.sysService.findByUserId(userId);
        if (sysUser != null && StringUtils.isNotEmpty(sysUser.getLoginWhiteIp())) {
            //获取当前用户IP
            Boolean result = XXPayUtil.ipAllow4Strong(ip, sysUser.getLoginWhiteIp(), null);
            if (!result) {
                _log.info("当前登录用户IP不在白名单中,userName={},requestIp={},loginWhiteIp={}", sysUser.getUserName(), ip, sysUser.getLoginWhiteIp());
                throw new ServiceException(RetEnum.RET_MGR_USER_IP_LIMIT);
            }
        }

        //当前用户已设置谷歌验证， 需要验证谷歌码是否正确
        if (sysUser.getGoogleAuthStatus() == MchConstant.PUB_YES) {
            boolean check = GoogleAuthenticatorUtil.checkByThrowException2(googleCode, sysUser.getGoogleAuthSecretKey());
            if (!check) {
                if (loginCountConfig != null && loginCountConfig != 0) {
                    int count = commonService.sysLoginFileIpRecordService.failCountByIp(ip, btSignConfig, btUrlConfig, loginCountConfig, loginToBlackType, username);
                    if (count < 0) {
                        throw new ServiceException(RetEnum.RET_MGR_USER_STOP);
                    }
                    _log.error("登录失败, 剩余登录次数:"+count);
                    throw new ServiceException(RetEnum.RET_MGR_LOGIN_FAIL, "剩余登录次数:"+count);
                }else {
                    _log.error("登录失败");
                    throw new ServiceException(RetEnum.RET_MGR_LOGIN_FAIL);
                }
            }
        }

        String token = jwtTokenUtil.generateToken(userDetails, ip);
        return token;
    }

    public String refreshToken(String oldToken) {
        String token = oldToken;
        String username = jwtTokenUtil.getUsernameFromToken(token);
        JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username);
        // 查看商户状态
        Byte status = user.getStatus();
        if(status == MchConstant.MGR_STATUS_STOP) {
            throw new ServiceException(RetEnum.RET_MGR_USER_STOP);
        }
        if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())){
            return jwtTokenUtil.refreshToken(token);
        }
        return null;
    }

}
